﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using HtmlAgilityPack;
using System.Security.Cryptography;

namespace Test1
{
    class Program
    {
        public static HttpClient httpClient = new HttpClient();//设置Public httpClient类，其可以自动管理Cookie，后续登陆过程中需要一直使用同一个类才能确保登陆状态

        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            bool LoginStatus = LoginMFsso();
            if(LoginStatus==true)
                SearchPN();
        }

        /// <summary>
        /// 请求帐号密码，登陆SSO
        /// </summary>
        /// <returns>ture=登陆成功</returns>
        public static bool LoginMFsso()
        {
            httpClient.MaxResponseContentBufferSize = 256000;//设置一些httpClient类的默认信息，如不设置会被SSO拒绝
            httpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36");
            httpClient.DefaultRequestHeaders.Add("Accept-Encoding","gzip, deflate");

            string url = "http://sso.xiamenair.com.cn/sso/login?token=yes&service=http://spare.xiamenair.com.cn/ssologin";//SSO网址
            HttpResponseMessage response = httpClient.GetAsync(new Uri(url)).Result;//连接并get SSO网页信息
            string result = response.Content.ReadAsStringAsync().Result; //result为SSO页面的html源码
            Console.WriteLine("请输入门户帐号："); 
            string username = Console.ReadLine();
            Console.WriteLine("请输入门户密码："); 
            string password = Console.ReadLine();
            password=GetMd5(password)+"-SSO";//密码名通过MD5加密后在加-SSO形成的字符串为Post的密码
            
            //构造登陆Post请求正文的内容
            List<KeyValuePair<String, String>> paramList = new List<KeyValuePair<String, String>>();
                paramList.Add(new KeyValuePair<string, string>("_eventId","submit"));
                paramList.Add(new KeyValuePair<string, string>("lanSelect", "0")); 
                paramList.Add(new KeyValuePair<string, string>("lt", "e1s1"));   
                paramList.Add(new KeyValuePair<string, string>("submit",""));//以上四条内容不会变，必须发送
                paramList.Add(new KeyValuePair<string, string>("username", username));
                paramList.Add(new KeyValuePair<string, string>("password", password));          
            //使用Post发送以上内容并得到响应
            response = httpClient.PostAsync(new Uri(url), new FormUrlEncodedContent(paramList)).Result;
            result = response.Content.ReadAsStringAsync().Result;
            //调用 HtmlAgilityPack按Xpath提取关键词
            var htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(result);       
            var title = htmlDoc.DocumentNode.SelectSingleNode("/html/head/title");//Xpath取页面标题
            var Sparetitle = title.InnerText.Replace("\r\n", "").Replace(" ", "").Trim();//去掉不需要的标签和字符。InnerText：提取<a>X</a>之间的文本X；OuterHtml:提取整个“<a>X</a>”。

            bool LoginStatus = false;
            if(Sparetitle =="厦门航空公司航材管理系统")
            {
                Console.WriteLine(Sparetitle+"已成功登陆");
                LoginStatus = true;
            }
            else
            {
                Console.WriteLine(Sparetitle+"登陆失败，请确认帐号密码是否正确");
                //LoginStatus=LoginMFsso();
            }
            return LoginStatus;
        }


        /// <summary>
        /// 登陆航材系统，查找件号的ID（VPN_ID）
        /// </summary>
        public static void SearchPN()
        {
            string PNurl="http://spare.xiamenair.com.cn/services/synpnquery/listPns/";//将部件查找的输入框内的件号，通过Post到该网址来获取VPN_ID
            string a= "<Envelope xmlns=\"http://www.w3.org/2003/05/soap-envelope\"><Body><listPns xmlns=\"synpnquery\" type=\"Select\"><Select xmlns=\"\" pageSize=\"10\" pageNo=\"1\"><query><VPN co=\"like\" type=\"string\"><vls><vl>";
            string b= "%</vl></vls></VPN></query><order><VPN asc=\"false\"/></order></Select></listPns></Body></Envelope>";
            Console.WriteLine("请输入待查件号（eg：0851HT-1）：");
            string PNinput=Console.ReadLine();
            string RequestString = a+ PNinput+ b;//拼接以上信息作为Post正文。

            httpClient.DefaultRequestHeaders.Add("req-stream-type","xml");//为Post和接受回复的正文重新设置xml格式，否则Post正文无法发送。
            httpClient.DefaultRequestHeaders.Add("res-stream-type","xml");
            HttpResponseMessage PNresponse = httpClient.PostAsync(new Uri(PNurl), new StringContent(RequestString)).Result;
            string PNresult = PNresponse.Content.ReadAsStringAsync().Result;//取到回复，同样是xml格式。
            //eg.PNresult值"<?xml version=\"1.0\" encoding=\"UTF-8\"?><Envelope xmlns=\"http://www.w3.org/2003/05/soap-envelope\"><Body><listPnsResponse xmlns=\"synpnquery\"><rows pageSize=\"10\" pageNo=\"1\" totalSizes=\"1\"><row><VPN_ID>
            //(接上一行)4914</VPN_ID><VPN>0851HT-1</VPN><PN_NAME>皮托管 / PITOT STATIC PROBE</PN_NAME><PN_TYPE>否</PN_TYPE><STORAGE_REQUEST></STORAGE_REQUEST></row></rows></listPnsResponse></Body></Envelope>"
            
            //调用 HtmlAgilityPack按Xpath提取关键词
            var htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(PNresult);       
            var ID = htmlDoc.DocumentNode.SelectSingleNode("/envelope[1]/body[1]/listpnsresponse[1]/rows[1]/row[1]/vpn_id[1]");//Xpath航材的VPN_ID号          
            var VPN_ID = ID.InnerText.Replace("\r\n", "").Replace(" ", "").Trim();//InnerText：提取<a>X</a>之间的文本X；OuterHtml:提取整个“<a>X</a>”。            
            
            string GetNumurl="http://spare.xiamenair.com.cn/services/public/custom2774/";
            a= "<Envelope xmlns=\"http://www.w3.org/2003/05/soap-envelope\"><Body><custom2774 xmlns=\"public\" type=\"Sql\"><Sql xmlns=\"\"><params><param type=\"int\" vl=\"";
            b= "\"/></params></Sql></custom2774></Body></Envelope>";
            RequestString = a + VPN_ID + b;//将VPN_ID再Post到以上网址，得到该件号航材库存的具体信息
            ShowPN(GetNumurl,RequestString);            
        }

        /// <summary>
        /// 根据VPN_ID，查找该件的具体信息
        /// <param GetNumurl="str" >航材库存的具体信息网址</param>
        /// <param RequestString="str" >Post正文</param>
        /// </summary>
        public static void ShowPN( string GetNumurl, string RequestString )
        {
            HttpResponseMessage Numresponse = httpClient.PostAsync(new Uri(GetNumurl), new StringContent(RequestString)).Result;
            string Numresult = Numresponse.Content.ReadAsStringAsync().Result;      
            //正则匹配出所需的信息及标签
            Match VPNreg = Regex.Match(Numresult, @"<VPN>.*?</VPN>");
            string VPN = VPNreg.Value.ToString().Replace("<VPN>", "").Replace("</VPN>", "");//件号
            Match CHNNAMEreg = Regex.Match(Numresult, @"<CHNNAME>.*?</CHNNAME>");
            string CHNNAME = CHNNAMEreg.Value.ToString().Replace("<CHNNAME>", "").Replace("</CHNNAME>", "");//中文名
            Match USED_QTYreg = Regex.Match(Numresult, @"<USED_QTY>.*?</USED_QTY>");
            string USED_QTY = USED_QTYreg.Value.ToString().Replace("<USED_QTY>", "").Replace("</USED_QTY>", "");//总库存
            Match XMN_USED_QTYreg = Regex.Match(Numresult, @"<XMN_USED_QTY>.*?</XMN_USED_QTY>");
            string XMN_USED_QTY = XMN_USED_QTYreg.Value.ToString().Replace("<XMN_USED_QTY>", "").Replace("</XMN_USED_QTY>", "");//厦门库存
            Match UNITreg = Regex.Match(Numresult, @"<UNIT>.*?</UNIT>");
            string UNIT = UNITreg.Value.ToString().Replace("<UNIT>", "").Replace("</UNIT>", "");//单位

            Console.WriteLine(string.Format("P/N={0}, Name={1}, 总库存={2} {4}, 厦门库存={3} {4}", VPN, CHNNAME, USED_QTY, XMN_USED_QTY, UNIT ));
        }


        /// <summary>
        /// MD5计算
        /// </summary>
        /// <param name="str">需要计算MD5的字符串</param>
        /// <returns>32位的字符串</returns>
        public static string GetMd5(string str)
        {
            // Convert the input string to a byte array and compute the hash.
            MD5 md5Hash = MD5.Create();
            byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(str));
            // Create a new Stringbuilder to collect the bytes
            // and create a string.
            StringBuilder sBuilder = new StringBuilder();
            // Loop through each byte of the hashed data 
            // and format each one as a hexadecimal string.
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }
            // Return the hexadecimal string.
            return sBuilder.ToString();

        }
    }
}
